package cn.edu.pku.nggis.remotesensingdigitalimageprocessing;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class KMeansClassifyProcess extends MinimalDistanceClassifyProcess
		implements ClassifyProcess {

	@Override
	public void process(Map<Integer, List<Point>> samplePixels,
			int[][] classifiedArray, int[][][] dataArray,
			Map<String, Object> params) {
		long maxdiff_before = 0, maxdiff_after = Integer.MAX_VALUE;
		List<muRecord> muList1 = getMuList(samplePixels, dataArray);
		List<muRecord> muList2;
		while (maxdiff_before != maxdiff_after) {
			classify(muList1, dataArray, classifiedArray);
			samplePixels = getSamplePixels(classifiedArray);
			muList2 = getMuList(samplePixels, dataArray);
			maxdiff_before = maxdiff_after;
			maxdiff_after = getMaxDiffInMu(muList1, muList2);
			muList1 = muList2;
		}
	}

	protected Map<Integer, List<Point>> getSamplePixels(int[][] classifiedArray) {
		Map<Integer, List<Point>> samplePixels = new HashMap<Integer, List<Point>>();
		for (int i = 0; i < classifiedArray.length; i++) {
			for (int j = 0; j < classifiedArray[0].length; j++) {
				int sample = classifiedArray[i][j];
				if (0 != sample) {
					if (!samplePixels.containsKey(sample)) {
						samplePixels.put(sample, new ArrayList<Point>());
					}
					samplePixels.get(sample).add(new Point(i, j));
				}
			}
		}
		return samplePixels;
	}

	protected long getMaxDiffInMu(List<muRecord> muList1, List<muRecord> muList2) {
		long maxdiff = 0;
		Collections.sort(muList1);
		Collections.sort(muList2);
		for (int i = 0; i < muList1.size(); i++) {
			long d = 0;
			long[] samples1 = muList1.get(i).samples;
			long[] samples2 = muList2.get(i).samples;
			for (int ite = 0; ite < samples1.length; ite++) {
				long di = samples1[ite] - samples2[ite];
				d += di * di;
			}
			if (d > maxdiff) {
				maxdiff = d;
			}
		}
		return maxdiff;
	}

}
